<template>
  <div v-loading="loading" class="wl-create-task">
    <i ref="backbutton" class="el-icon-back wl-back" @click="handleBack()"> 返回</i>
    <a :style="(showPage==1)?'':'display:none;'" class="wl-spread" @click="spreadCollapse()">{{ spread?'关闭':'展开' }}</a>
    <!-- 选择发布项目 -->
    <div ref="page1" :class="showPage==1?'wl-show':'wl-hide'">
      <el-collapse v-model="activeNames">
        <el-collapse-item v-for="(item, index) in environments" :key="item.id" :title="item.env_name" :name="index" class="wl-task-project">
          <div class="wl-task-project__search">
            <el-input v-model="form.queryName[index]" placeholder="请输入内容" class="wl-input" @input="handleQuery(item.id)">
              <el-button slot="append" icon="el-icon-search" class="wl-search" @click="handleQuery(item.id)" />
            </el-input>
          </div>
          <div v-if="!item.projects||item.projects.length===0" class="wl-task-project__no-data">这里还没有项目</div>
          <a v-for="prj in item.projects" :key="prj.id" :class="tagClass[index%3]" @click="handleSelectProject(prj.id, prj.name, item.env_name)">{{ prj.name }}</a>
        </el-collapse-item>
      </el-collapse>
    </div>
    <!-- 发布项目配置 -->
    <div ref="page2" :class="showPage==2?'wl-show':'wl-hide'">
      <el-form ref="form" :model="form" :rules="rules" label-width="100px">
        <el-form-item label="上线项目" prop="project_name">
          <el-input v-model="form.project_name" class="wl-input" disabled />
        </el-form-item>
        <el-form-item label="上线环境" prop="environment_name">
          <el-input v-model="form.environment_name" class="wl-input" disabled />
        </el-form-item>
        <el-form-item label="上线单标题" prop="task_name">
          <el-input v-model="form.task_name" placeholder="请输入上线单名称" class="wl-input" />
        </el-form-item>
        <el-form-item v-if="project.repo_mode==='tag'" label="选取Tag" prop="tag">
          <el-select v-model="form.tag" v-loading="loading_tag" placeholder="选取Tag" class="wl-input">
            <el-option v-for="item in tags" :key="item" :label="item" :value="item" />
          </el-select>
          <i class="el-icon-refresh wl-task-refresh" @click="handleRefreshTag()" />
        </el-form-item>
        <el-form-item v-if="project.repo_mode==='branch'" label="选取分支" prop="branch">
          <el-select v-model="form.branch" v-loading="loading_branch" placeholder="选取分支" class="wl-input" @change="handleSelectBranch()">
            <el-option v-for="item in branchs" :key="item" :label="item" :value="item" />
          </el-select>
          <i class="el-icon-refresh wl-task-refresh" @click="handleRefreshBranch()" />
        </el-form-item>
        <el-form-item v-if="project.repo_mode==='branch'" label="选取版本" prop="commit">
          <el-select v-model="form.commit" v-loading="loading_commit" placeholder="先选取分支再选取版本" class="wl-input">
            <el-option v-for="item in commits" :key="item.id" :label="item.id+' # '+item.message+' by '+item.name" :value="item.id" />
          </el-select>
          <i class="el-icon-refresh wl-task-refresh" @click="handleRefreshCommit()" />
        </el-form-item>
        <el-form-item label="全量/增量" prop="file_list">
          <el-radio-group v-model="form.file_transmission_mode" @change="handleFileMode()">
            <el-radio label="1">全量上线</el-radio>
            <el-radio label="2">
              <el-popover placement="top-start" trigger="hover" class="wl-popover">
                <div class="wl-popover">
                  <p>1.上线指定目录：dir_name</p>
                  <p>2.上线指定文件：file_name</p>
                  <p>3.通配符 file*</p>
                </div>
                <span slot="reference" >指定文件<i class="el-icon-info" style="margin-left: 2px;" /></span>
              </el-popover>
            </el-radio>
          </el-radio-group>
          <el-button v-if="form.file_transmission_mode==='2'" type="primary" round style="margin-left: 50px;" @click="handleOpenFileDialog()">拉取列表</el-button>
        </el-form-item>
        <el-form-item v-if="form.file_transmission_mode==='2'" class="wl-files">
          <codemirror ref="cmEditer1" :value="form.file_list" :options="cmOptions1" :placeholder="filelist_placeholder" class="wl-codemirror"></codemirror>
        </el-form-item>
        <el-form-item label="选取服务器" prop="servers">
          <el-radio-group v-model="form.server_type" @change="handleServerType()">
            <el-radio label="1">全量服务器上线</el-radio>
            <el-radio label="2">自定义服务器上线</el-radio>
          </el-radio-group>
        </el-form-item>
        <el-form-item v-if="form.server_type==='2'">
          <div class="wl-task-servers">
            <el-tag v-for="server in form.servers" :key="server.id" type="info" size="medium" closable @close="handleTagClose(server.id)">{{ server.name }}</el-tag>
          </div>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" class="wl-append" @click="handleSubmitTask()">提交</el-button>
        </el-form-item>
      </el-form>
    </div>

    <!-- 弹出从仓库拉取更新文件列表 -->
    <el-dialog title="从仓库拉取更新文件列表" 
      :visible.sync="form_git.show_dialog_git" 
      v-loading.fullscreen.lock="loading" 
      :close-on-click-modal="false" 
      width="700px" class="wl-git-dialog" size="small">
      <el-checkbox :indeterminate="form_git.isIndeterminate" v-model="form_git.checkAll" @change="handleFilesCheckAllChange">全选</el-checkbox>
      <el-checkbox-group v-model="form_git.select_files" @change="handleCheckedFilesChange">
        <el-checkbox v-for="file in form_git.diffFiles" 
          :label="file.name"
          :key="file.name" 
          :disabled="file.type==='delete'"
          style="display:block;">
          <i :class="getFileClass(file)"></i><pre :class="getFileColor(file)">{{file.name}}</pre></el-checkbox>
      </el-checkbox-group>
      <div slot="footer" class="dialog-footer">
        <el-button v-loading="form_git.loading" type="primary" @click="handlePullFile()">确 定</el-button>
        <el-button @click="handleClosePullFile()">取 消</el-button>
      </div>
    </el-dialog>
  </div>
</template>

<script>
import io from 'socket.io-client'
import { getTasks, cteateTask, updateTask } from '@/api/task'
import { getEnvironment } from '@/api/env'
import { getProject, getProjects } from '@/api/project'

import { codemirror } from 'vue-codemirror'
import 'codemirror/lib/codemirror.css'
import 'codemirror/addon/display/fullscreen.css';
import 'codemirror/mode/shell/shell.js'
import 'codemirror/addon/display/fullscreen.js';
import 'codemirror/addon/display/placeholder'

export default {
  name: 'CreateTask',
  components: {
    codemirror
  },
  data() {
    var checkTag = (rule, value, callback) => {
      if (this.project.repo_mode !== 'tag') {
        return callback()
      }
      if (!value || value.trim() === '') {
        return callback(new Error('选取Tag'))
      }
      return callback()
    }
    var checkBranch = (rule, value, callback) => {
      if (this.project.repo_mode !== 'branch') {
        return callback()
      }
      if (!value || value.trim() === '') {
        return callback(new Error('请选取分支'))
      }
      return callback()
    }
    var checkCommit = (rule, value, callback) => {
      if (this.project.repo_mode !== 'branch') {
        return callback()
      }
      if (!value || value.trim() === '') {
        return callback(new Error('请选取版本'))
      }
      return callback()
    }
    var checkFilelist = (rule, value, callback) => {
      if (this.form.file_transmission_mode !== '2') {
        return callback()
      }
      if (!value || value.trim() === '') {
        return callback(new Error('请输入文件列表'))
      }
      return callback()
    }
    const cmExtraKeys = {
      'F11': function(cm) {
        cm.setOption('fullScreen', !cm.getOption('fullScreen'))
        cm.focus();
      },
      'Esc': function(cm) {
        if (cm.getOption('fullScreen')) {
          cm.setOption('fullScreen', false)
          cm.focus()
        }
      } 
    }
    return {
      loading: false,
      params: {
        flag: '',    // create,update,view
        context: {}, // 父页面传递过来的参加，返回时带给父页面恢复上下文
        task: {},    // 任务新建状态时，是参考模板；修改状态时是要修改的任务
        project: {}
      },
      websock: null,
      spread: true,
      showPage: 1,
      tmp_environments: [],
      environments: [],
      activeNames: [],
      form_git: {
        loading: false,
        show_dialog_git: false,
        checkAll: false,
        isIndeterminate: false,
        diffFiles:[],
        select_files: []
      },
      form: {
        queryName: [],
        task_id: '',
        task_name: '',
        project_name: '',
        environment_name: '',
        tag: '',
        branch: '',
        commit: '',
        file_transmission_mode: '1',
        file_list: '',
        server_type: '1',
        servers: []
      },
      rules: {
        task_name: [{ required: true, message: '请输入上线单名称', trigger: 'blur' }],
        tag: [{ validator: checkTag, trigger: 'blur' }],
        branch: [{ validator: checkBranch, trigger: 'blur' }],
        commit: [{ validator: checkCommit, trigger: 'blur' }],
        servers: [{ required: true, message: '请选择服务器', trigger: 'blur' }],
        file_list: [{ validator: checkFilelist, trigger: 'blur' }]
      },
      project: {},
      tags: [],
      branchs: [],
      commits: [],
      loading_tag: false,
      loading_branch: false,
      loading_commit: false,
      tagClass: ['wl-el-color-1', 'wl-el-color-2', 'wl-el-color-3'],
      filelist_placeholder: 'index.php\nREADME.md\ndir_name\nfile*',
      coder: null, // 编辑器实例
      cmOptions1: {
        value: '',
        mode: "text/x-sh",
        theme: "default", // solarized light,base16-light,cobalt
        readOnly: false,
        tabSize: 2,
        lineNumbers: true,
        line: true,
        readOnly: false,
        extraKeys: cmExtraKeys
      },
    }
  },
  mounted() {
    const params = this.$route.params
    this.params.context = params.context
    this.params.flag = params.flag
    this.params.task = params.data
    this.initWebSocket()
    if (this.params.flag === 'create' && (!this.params.task)) {
      this.showPage = 1
      this.getEnvironmentList()
    } else if (this.params.flag === 'create' && this.params.task) {
      this.showPage = 2
      this.params.project = params.project
      this.initCreateByTask(this.params.task, this.params.project)
    } else if (this.params.flag === 'update') {
      this.showPage = 2
      this.initUpdateTask(this.params.task)
    }
    setTimeout(() => { this.initBindCodemirror() }, 1) // 延时执行，否则vue组件mounte会报错
  },
  beforeDestroy() {
    this.websock.close()
  },
  methods: {
    handleBack() { // 返回
      if (this.params.flag === 'update') {
        this.$router.replace({ name: 'WalleDeploy', params: this.params.context })
        return
      }
      if (this.showPage == 2 && (!this.params.task)) {
        this.showPage = 1
      } else {
        this.$router.replace({ name: 'WalleDeploy', params: this.params.context })
      }
    },
    spreadCollapse() { // 全部展开和关闭项目选择
      this.spread = !this.spread
      this.activeNames = []
      if (this.spread) {
        for (var i = 0; i < this.environments.length; i++) {
          this.activeNames.push(i)
        }
      }
    },
    initBindCodemirror() { // 让codemirror支持双向绑定，否则只支持单向:属性->codemirror
      // 因为条件codemirror在全量模式下不显示，所有要判断是加载
      if (this.form.file_transmission_mode === '2') { 
        this.coder = this.$refs.cmEditer1.codemirror
        this.coder.on('change', (coder) => {
          this.form.file_list = coder.getValue()
          if (this.$emit) {
            this.$emit('input', this.form.file_list)
          }
        })
      } else {
        this.coder = null
      }
    },
    handleQuery(envid) { // 根据环境查询项目
      let idx = -1
      for (const i in this.environments) {
        if (this.environments[i].id === envid) {
          idx = i
          break
        }
      }
      if (idx < 0) {
        return
      }
      const env = this.environments[idx]
      getProjects(30, 1, this.form.queryName[idx], envid).then(response => {
        this.loading = false
        if (!response.data || response.data.code !== 0) {
          this.$message({ type: 'error', message: (response.data && response.data.message) ? response.data.message : '请求数据异常！' })
          return
        }
        env.projects = response.data.data.list
        this.$forceUpdate() // 多层v-for循环嵌套导致v-model双向绑定不稳定，强制更新
      }).catch(error => {
        this.loading = false
        this.$message({ type: 'error', message: '请求失败!' })
      })
    },
    getEnvironmentList() {
      getEnvironment().then(response => {
        this.loading = false
        if (!response.data || response.data.code !== 0) {
          this.$message({ type: 'error', message: (response.data && response.data.message) ? response.data.message : '请求数据异常！' })
          return
        }
        this.tmp_environments = response.data.data.list
        for (const i in this.tmp_environments) {
          this.getProject(this.tmp_environments[i].id)
        }
      }).catch(error => {
        this.loading = false
        this.$message({ type: 'error', message: '请求失败!' })
      })
    },
    getProject(envid) {
      getProjects(300, 1, '', envid).then(response => {
        this.loading = false
        if (!response.data || response.data.code !== 0) {
          this.$message({ type: 'error', message: (response.data && response.data.message) ? response.data.message : '请求数据异常！' })
          return
        }
        const projects = response.data.data.list
        for (let i = this.tmp_environments.length - 1; i >= 0; i--) {
          if (envid !== this.tmp_environments[i].id) {
            continue
          }
          this.tmp_environments[i].projects = projects
          if (projects.length > 0) {
            // 按环境编号有序插入
            let addflag = false
            for(let k = 0; k < this.environments.length; k++) {
              if (this.tmp_environments[i].id <= this.environments[k].id) {
                this.environments.splice(k, 0, this.tmp_environments[i])
                addflag = true;
                break;
              }
            }
            if (!addflag) {
              this.environments.push(this.tmp_environments[i])
            }
            if (this.spread) {
              this.activeNames.push(this.environments.length - 1)
            }
          }
        }
        this.$forceUpdate() // 多层v-for循环嵌套导致v-model双向绑定不稳定，强制更新
      }).catch(error => {
        console.log(error)
        this.loading = false
        this.$message({ type: 'error', message: '请求项目列表错误!' })
      })
    },
    handleServerType() {
      this.form.servers = []
      for (const i in this.project.servers_info) {
        this.form.servers.push({ ...this.project.servers_info[i] })
      }
    },
    handleTagClose(serverId) {
      for (let i = this.form.servers.length - 1; i >= 0; i--) {
        if (this.form.servers[i].id === serverId) {
          this.form.servers.splice(i, 1)
          break
        }
      }
    },
    handleSelectProject(projectId, projectName, env_name) { // 选择项目创建上线单
      this.showPage = 2
      this.project = {}
      this.tags = []
      this.branchs = []
      this.commits = []
      this.form.project_name = projectName
      this.form.environment_name = env_name
      this.form.tag = this.getLocalValue('project:tag:' + projectId)
      this.form.branch = this.getLocalValue('project:branch:' + projectId)
      this.form.commit = ''
      this.websock.emit('open', { project_id: projectId })
      getProject(projectId).then(response => {
        this.loading = false
        if (!response.data || response.data.code !== 0) {
          this.$message({ type: 'error', message: (response.data && response.data.message) ? response.data.message : '请求数据异常！' })
          return
        }
        this.project = response.data.data
        this.form.servers = []
        for (const i in this.project.servers_info) {
          this.form.servers.push({ ...this.project.servers_info[i] })
        }
        if (this.project.repo_mode === 'branch') {
          if (this.form.branch && this.form.branch !== '') {
            this.branchs = [this.form.branch]
            this.handleRefreshCommit()
          } else {
            this.handleRefreshBranch()
          }
        } else if (this.project.repo_mode === 'tag') {
          this.handleRefreshTag()
        }
      }).catch(error => {
        this.loading = false
        this.$message({ type: 'error', message: '请求失败!' })
      })
    },
    initUpdateTask(task) {
      this.project = {}
      this.tags = []
      this.branchs = []
      this.commits = []
      this.form.task_id = task.id
      this.form.task_name = task.name
      this.form.project_name = task.project_name
      this.form.environment_name = task.environment_name
      this.form.tag = task.tag
      this.form.branch = task.branch
      this.form.commit = task.commit_id
      this.form.file_transmission_mode = task.file_transmission_mode+''
      this.form.file_list = task.file_list
      this.form.server_type = '1'
      this.form.servers = task.servers_info
      this.websock.emit('open', { project_id: task.project_id })
      getProject(task.project_id).then(response => {
        this.loading = false
        if (!response.data || response.data.code !== 0) {
          this.$message({ type: 'error', message: (response.data && response.data.message) ? response.data.message : '请求数据异常！' })
          return
        }
        this.project = response.data.data
        if (this.form.servers.length < this.project.servers_info.length) {
          this.form.server_type = '2'
        }
        if (this.project.repo_mode === 'branch') {
          if (this.form.branch && this.form.branch !== '') {
            this.branchs = [this.form.branch]
            this.handleRefreshCommit()
          } else {
            this.handleRefreshBranch()
          }
        } else if (this.project.repo_mode === 'tag') {
          this.handleRefreshTag()
        }
      }).catch(error => {
        this.loading = false
        this.$message({ type: 'error', message: '请求失败!' })
      })
    },
    initCreateByTask(task, project) {
      const newtask = this.params.flag === 'create'
      this.project = {}
      this.tags = []
      this.branchs = []
      this.commits = []
      this.form.task_id = ''
      this.form.task_name = task.name + '-' + project.environment_name
      this.form.project_name = task.project_name
      this.form.environment_name = project.environment_name
      this.form.tag = task.tag
      this.form.branch = task.branch
      this.form.commit = task.commit_id
      this.form.file_transmission_mode = task.file_transmission_mode+''
      this.form.file_list = task.file_list
      this.form.server_type = '1'
      this.form.servers = []
      this.websock.emit('open', { project_id: task.project_id })
      getProject(project.project_id).then(response => {
        this.loading = false
        if (!response.data || response.data.code !== 0) {
          this.$message({ type: 'error', message: (response.data && response.data.message) ? response.data.message : '请求数据异常！' })
          return
        }
        this.project = response.data.data
        this.form.servers = []
        for (const i in this.project.servers_info) {
          this.form.servers.push({ ...this.project.servers_info[i] })
        }
        if (this.project.repo_mode === 'branch') {
          if (this.form.branch && this.form.branch !== '') {
            this.branchs = [this.form.branch]
            this.handleRefreshCommit()
          } else {
            this.handleRefreshBranch()
          }
        } else if (this.project.repo_mode === 'tag') {
          this.handleRefreshTag()
        }
      }).catch(error => {
        this.loading = false
        this.$message({ type: 'error', message: '请求失败!' })
      })
    },
    initWebSocket() {
      // 创建websocket连接
      this.websock = io('/walle', {
        path: '/socket.io',
        transports: ['websocket', 'polling'], // ['polling', 'websocket']
        autoConnect: false
      })
      // 系统事件处理
      this.websock.on('connect', this.onConnect) // 打开连接
      this.websock.on('reconnect', this.onReconnect) // 打开连接
      this.websock.on('disconnect', this.onDisconnect) // 关闭连接
      this.websock.on('error', this.onError) // 连接异常
      this.websock.on('connect_timeout', this.onConnectTimeout) // 连接异常
      this.websock.on('connect_error', this.onConnectError) // 连接异常
      this.websock.on('reconnect_error', this.onReconnectError) // 连接异常
      this.websock.on('reconnect_failed', this.onReconnectFailed) // 连接异常
      this.websock.on('ping', this.onPing) // Ping
      this.websock.on('pong', this.onPong) // Pong
      // 应用内消息处理： tags, branches, commits
      this.websock.on('construct', this.onMessage)
      this.websock.on('tags', this.onMessage)
      this.websock.on('branches', this.onMessage)
      this.websock.on('commits', this.onMessage)
      this.websock.on('diff_files', this.onMessage)
      this.websock.open() // 打开websocket连接
    },
    onConnect() {
      console.log('打开连接')
    },
    onReconnect() {
      console.log('重新连接')
    },
    onDisconnect(reason) {
      console.log('关闭连接', reason)
    },
    onConnectError(error) {
      console.log('连接错误', error)
    },
    onError(error) {
      console.log('错误', error)
    },
    onConnectTimeout(timeout) {
      console.log('连接超时', timeout)
    },
    onReconnectError(error) {
      console.log('重新连接错误', error)
    },
    onReconnectFailed() {
      console.log('重新连接失败')
    },
    websockClose() {
      console.log('关闭连接')
    },
    websockError(e) {
      console.log('连接异常', e)
    },
    onPing() {
      // console.log('Ping')
    },
    onPong(latency) {
      // console.log('Pong', latency)
    },
    onMessage(data) {
      console.log('接收消息', data)
      switch (data.event) {
        case 'tags': this.doTagsMessage(data.event, data.data); break
        case 'branches': this.doBranchesMessage(data.event, data.data); break
        case 'commits': this.doCommitsMessage(data.event, data.data); break
        case 'diff_files': this.doDiffFilesMessage(data.event, data.data); break
        case 'construct': this.doConstructMessage(data.event, data.data); break
      }
    },
    doConstructMessage(event, data) {
      // this.handleRefreshCommit()
    },
    doTagsMessage(event, data) {
      this.loading_tag = false
      if (data.error) {
        this.$message({ type: 'error', message: data.error })
        return
      }
      this.tags = data
      if (!this.tags || this.tags.length === 0) {
        this.form.tag = ''
      } else {
        for (const i in this.tags) {
          if (this.tags[i] === this.form.tag) {
            return
          }
        }
        this.form.tag = this.tags[0]
      }
    },
    doBranchesMessage(event, data) {
      this.loading_branch = false
      if (data.error) {
        this.$message({ type: 'error', message: data.error })
        return
      }
      this.branchs = data
      if (!this.branchs || this.branchs.length === 0) {
        this.form.branch = ''
        this.form.commit = ''
      } else if (this.form.branch === '') {
        this.form.branch = this.branchs[0]
        this.handleRefreshCommit()
      } else {
        for (const i in this.branchs) {
          if (this.branchs[i] === this.form.branch) {
            return
          }
        }
        this.form.branch = this.branchs[0]
        this.handleRefreshCommit()
      }
    },
    doCommitsMessage(event, data) {
      this.loading_commit = false
      if (data.error) {
        this.$message({ type: 'error', message: data.error })
        return
      }
      this.commits = data
      if (!this.commits || this.commits.length === 0) {
        this.form.commit = ''
      } else {
        for (const i in this.commits) {
          if (this.commits[i].id === this.form.commit) {
            return
          }
        }
        this.form.commit = this.commits[0].id
      }
    },
    doDiffFilesMessage(event, data) {
      this.loading_commit = false
      this.form_git.loading = false
      if (data.error) {
        this.$message({ type: 'error', message: data.error })
        return
      }
      if (data.length == 0) {
        this.form_git.show_dialog_git = false
        this.$message({ type: 'error', message: '未拉取到仓库的文件列表，请检查要发布的版本是否正确，代码是否已提交仓库！' })
        return
      }
      this.form_git.diffFiles = data.sort(function compare(f1, f2) { return (f1.name === f2.name) ? 0 : (f1.name > f2.name ? 1 : -1) })
      this.form_git.checkAll = true
      let files = []
      for(let i in this.form_git.diffFiles) {
        if (this.form_git.diffFiles[i].type !== 'delete') {
          files.push(this.form_git.diffFiles[i].name)
        }
      }
      this.form_git.select_files = files
    },
    handleRefreshTag() {
      this.loading_tag = true
      this.websock.emit('tags')
    },
    handleRefreshBranch() {
      this.loading_branch = true
      this.websock.emit('branches')
    },
    handleRefreshCommit() {
      this.loading_commit = true
      if (this.form.branch && this.form.branch !== '') {
        this.websock.emit('commits', { branch: this.form.branch })
      }
    },
    handleSelectBranch() {
      this.commits = []
      this.form.commit = ''
      this.handleRefreshCommit()
    },
    handleFileMode() {
      this.initBindCodemirror()
    },
    handleOpenFileDialog() {
      this.form_git.loading = true
      this.form_git.checkAll = false
      this.form_git.diffFiles = []
      this.form_git.show_dialog_git = true
      this.websock.emit('diff_files', { commit_id: this.form.commit })
    },
    handleFilesCheckAllChange(value) {
      let files = []
      if (value) {
        for(let i in this.form_git.diffFiles) {
          if (this.form_git.diffFiles[i].type !== 'delete') {
            files.push(this.form_git.diffFiles[i].name)
          }
        }
      }
      this.form_git.select_files = files
      this.form_git.isIndeterminate = false;
    },
    handleCheckedFilesChange(value) {
      let cnt = 0
      for(let i in this.form_git.diffFiles) {
        if (this.form_git.diffFiles[i].type !== 'delete') {
          cnt++
        }
      }
      this.form_git.checkAll = value.length === cnt;
      this.form_git.isIndeterminate = value.length > 0 && value.length < cnt;
    },
    handlePullFile() {  // 更新摘取的文件列表
      if (this.form_git.loading) {
        return
      } 
      this.form_git.show_dialog_git = false
      const selfiles = (this.form_git.select_files === null) ? [] : this.trimStringList(this.form_git.select_files).sort()
      const taskfiles = (this.form.file_list === null) ? [] : this.trimStringList(this.form.file_list.split('\n')).sort()
      let files = selfiles.concat(taskfiles).sort()
      for(let i = files.length - 1; i >= 0; i--) { // 去重
        if (files[i] == files[i - 1]) {
          files.splice(i, 1);
        }
        if (files[i] === '') {
          files.splice(i, 1);
        }
      }
      this.form.file_list = files.join('\n')
    },
    handleClosePullFile() {
      this.form_git.loading = false
      this.form_git.show_dialog_git = false
    },
    handleSubmitTask() { // 提交上线单
      this.$refs.form.validate((valid) => {
        if (!valid) {
          return false
        }
        let servers = ''
        for (const i in this.form.servers) {
          servers += (servers === '' ? '' : ',') + this.form.servers[i].id
        }
        const task = {
          name: this.form.task_name,
          project_id: this.project.id,
          servers: servers,
          commit_id: this.form.commit,
          branch: this.form.branch,
          file_transmission_mode: this.form.file_transmission_mode,
          file_list: this.form.file_transmission_mode === '2' ? this.form.file_list : '',
          tag: this.form.tag
        }
        if (this.params.flag === 'create') {
          cteateTask(task).then(response => {
            this.loading = false
            if (!response.data || response.data.code !== 0) {
              this.$message({ type: 'error', message: (response.data && response.data.message) ? response.data.message : '提交上线单异常！' })
              return
            }
            if (task.tag && task.tag !== '') {
              this.setLocalValue('project:tag:' + task.project_id, task.tag)
            }
            if (task.branch && task.branch !== '') {
              this.setLocalValue('project:branch:' + task.project_id, task.branch)
            }
            this.$message({ type: 'success', message: '新建上线单【' + task.name + '】成功!' })
            this.$router.replace({ name: 'WalleDeploy', params: this.params.context }) // 返回
          }).catch(error => {
            this.loading = false
            this.$message({ type: 'error', message: '提交上线单失败!' })
          })
        } else if (this.params.flag === 'update') {
          updateTask(this.params.task.id, task).then(response => {
            this.loading = false
            if (!response.data || response.data.code !== 0) {
              this.$message({ type: 'error', message: (response.data && response.data.message) ? response.data.message : '更新上线单异常！' })
              return
            }
            if (task.tag && task.tag !== '') {
              this.setLocalValue('project:tag:' + task.project_id, task.tag)
            }
            if (task.branch && task.branch !== '') {
              this.setLocalValue('project:branch:' + task.project_id, task.branch)
            }
            this.$message({ type: 'success', message: '更新上线单【' + task.name + '】成功!' })
            this.$router.replace({ name: 'WalleDeploy', params: this.params.context }) // 返回
          }).catch(error => {
            this.loading = false
            this.$message({ type: 'error', message: '更新上线单失败!' })
          })
        }
      })
    },
    getFileClass(file) {
      switch(file.type) {
        case 'add': return 'el-icon-plus wl-add'
        case 'modify': return 'el-icon-upload2 wl-update'
        case 'delete': return 'el-icon-close wl-delete'
        default: return ''
      }
    },
    getFileColor(file) {
      switch(file.type) {
        case 'add': return 'wl-add wl-fill-line'
        case 'modify': return 'wl-update wl-fill-line'
        case 'delete': return 'wl-delete wl-fill-line'
        default: return 'wl-fill-line'
      }
    },
    trimStringList(lines) {
      for(let i in lines) {
        lines[i] = lines[i].trim()
      }
      return lines
    }
  }
}
</script>

<style scoped>
  .wl-create-task >>> label {
    font-weight: normal;
  }
  .wl-back {
    color: #1890ff;
    font-size: 14px;
    cursor: pointer;
  }
  .wl-spread {
    margin-left: 16px;
    color: #1890ff;
    font-size: 14px;
    cursor: pointer;
  }
  .wl-hide {
    margin-top: 20px;
    display: none;
  }
  .wl-show {
    margin-top: 20px;
    display: block;
  }
  .wl-search {
    background:#f5f7fa;
  }
  .wl-input {
    width: 250px;
  }
  .wl-task-project{
    position: relative;
  }
  .wl-task-project__search {
    position: absolute;
    top: 10px;
    right: 40px;
  }
  .wl-task-project__no-data {
    text-align: center;
  }
  .el-collapse-item__content a {
    min-width: 150px;
    border-color: #6fb3e0;
    display: inline-block;
    color: #FFF!important;
    cursor: pointer;
    text-align: center;
    vertical-align: middle;
    margin: 10px 12px;
    padding: 8px 0px;
  }
  .el-collapse-item__content a:hover {
    font-weight: 700;
  }
  .wl-el-color-1 {
    background-color:#87b87f;
  }
  .wl-el-color-2 {
    background-color:#ffb752;
  }
  .wl-el-color-3 {
    background-color: #1890ff;
  }
  .wl-task-filelist {
    width: 600px;
  }
  .wl-task-filelist >>> .el-textarea__inner {
    min-height: 150px!important;
    overflow: auto;
  }
  .wl-task-servers {
    width: 300px;
    border: 1px dashed #ddd;
    border-radius: 4px;
    padding: 10px;
    display: -ms-flexbox;
    display: flex;
    -ms-flex-direction: column;
    flex-direction: column;
  }
  .wl-create-task >>> .el-form-item__content {
    font-size: 16px;
  }
  .wl-task-servers >>> .el-tag--info {
    display: block;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    position: relative;
    margin-bottom: 10px;
  }
  .wl-task-servers >>> .el-tag .el-icon-close {
    position: absolute;
    right: 5px;
    top: 6px;
  }
  .wl-task-refresh {
    margin-left: 10px;
    color: #666;
    margin-top: 4px;
    cursor: pointer;
    font-size: 18px;
    font-weight: 600;
  }
  .wl-popover {
    display:inline-block;
    vertical-align:top;
    margin-left:5px
  }
  .wl-popover p {
    line-height: 8px;
  }
  .wl-popover i {
    color: #606266;
  }
  .wl-git-dialog >>> .el-dialog__body {
    padding: 0px 20px;
    max-height: 600px;
    overflow: auto;
  }
  .wl-git-dialog >>> .el-checkbox-group {
    max-height: calc(100vh - 300px);
  }
  .wl-git-dialog >>> .el-checkbox__label>i:before {
    font-size: 6px;
    padding-right: 5px;
  }
  .wl-git-dialog >>> .wl-add {
    color: green;
  }
  .wl-git-dialog >>> .wl-update {
    color: blue;
  }
  .wl-git-dialog >>> .wl-delete {
    color: red;
  }
  .wl-fill-line {
    display: inline-block;
    margin: 0;
  }
  .wl-codemirror {
    border: 1px solid#C0C4CC;
  }
  .wl-files {
    max-width: 900px;
    min-width: 500px;
  }
  .wl-files >>> .CodeMirror { 
    height: 200px;
    line-height : 130%;
    font-family: Helvetica Neue,Helvetica,Arial,sans-serif;
    font-size: 12px;
  }
  .wl-files >>> .CodeMirror-fullscreen {
    position: fixed!important;
    top: 0; left: 0; right: 0; bottom: 0;
    height: auto;
    z-index: 1001;
  }
  .wl-files >>> .CodeMirror pre.CodeMirror-placeholder { 
    color: #999; 
  }
</style>
